package cz.possoft.explorer.meta;

import java.util.Map;

import cz.possoft.explorer.resolver.Resolver;
import cz.possoft.explorer.resolver.method.MethodKey;
import cz.possoft.explorer.resolver.method.MethodResolver;

/**
 * Metainformation about single Java class. C is type of class and T is type for keys used by Resolver.
 * 
 * @author <a href="mailto:mposolda@gmail.com">Marek Posolda</a>
 * @version $Revision$
 */
public class ClassMetadata<C, T>
{
   private final Class<C> clazz;
   
   private final Class<? super C> supertypeClazz;
   
   private final Class<?>[] interfaceClasses;
   
   private final Map<T, Class<?>> fields; 
   
   private final Resolver<C, T> resolver;
    
   // key type hardcoded to MethodKey right now.
   private final Map<MethodKey, MethodMetadata> methods; 
   
   private final MethodResolver<C, MethodKey> methodResolver;
   
   public ClassMetadata(Class<C> clazz, Resolver<C, T> resolver, MethodResolver<C,MethodKey> methodResolver)
   {
      this.clazz = clazz;
      supertypeClazz = clazz.getSuperclass();
      interfaceClasses = clazz.getInterfaces();
      fields = resolver.getFields(clazz, null);
      this.resolver = resolver;
      this.methodResolver = methodResolver;
      this.methods = methodResolver.getMethods(clazz, null);
   }

   public Class<C> getClazz()
   {
      return clazz;
   }

   public Class<? super C> getSupertypeClazz()
   {
      return supertypeClazz;
   }

   public Class<?>[] getInterfaceClasses()
   {
      return interfaceClasses;
   }

   /**
    * By default is object "o" unused. It is used only when we are using DelegateToResolverClassMetadata
    * 
    * @param o
    * @return map with fields
    */
   public Map<T, Class<?>> getFields(C o)
   {
      return fields;
   }

   public Resolver<C, T> getResolver()
   {
      return resolver;
   }

   public MethodResolver<C, MethodKey> getMethodResolver()
   {
      return methodResolver;
   }

   /**
    * By default is object "o" unused. 
    * 
    * @param o
    * @return map with method metadata
    */   
   public Map<MethodKey, MethodMetadata> getMethods(C o)
   {
      return methods;
   }
   
   /**
    * Backwards compatibility and needed in JSP pages.
    * 
    * @return map with method metadata
    */
   public Map<MethodKey, MethodMetadata> getMethods()
   {
      return getMethods(null);
   }
      
}

